package com.huxi.lang.text;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;

/**
 * URI模板内容变量替换构建器
 * 
 * @author jian.wu
 *
 */
public class UriFormatter {

	protected static class CompKey {
		protected final String comp;
		protected final String key;

		private CompKey(String comp, String key) {
			this.comp = comp;
			this.key = key;
		}
	}

	private final String pattern;
	private final CompKey[] comps;
	private final boolean quiet;

	private UriFormatter(String pattern, CompKey[] comps, boolean quiet) {
		this.pattern = pattern;
		this.comps = comps;
		this.quiet = quiet;
	}

	public String getPattern() {
		return pattern;
	}

	public boolean isMutable() {
		return comps != null;
	}

	/**
	 * 格式化消息模板内容，替换变量内容
	 * 
	 * @param args 变量哈希表
	 * @return 消息模板变量替换后内容
	 * @throws IllegalArgumentException 替换变量内容失败
	 */
	public String build(@SuppressWarnings("rawtypes") Map args) throws IllegalArgumentException {
		if (comps == null) {
			return pattern;
		}
		final StringBuilder sb = new StringBuilder(128);
		if (args == null) {
			args = Collections.emptyMap();
		}
		for (CompKey item : comps) {
			String kk = item.key;
			if (kk == null) {
				sb.append(item.comp);
			} else {
				Object vv = args.get(kk);
				if (vv == null) {
					if (!args.containsKey(kk)) {
						if (quiet) {
							sb.append('{').append(kk).append('}');
						} else {
							throw new IllegalArgumentException("URI模板内容替换变量失败，不存在的命名变量 = " + kk);
						}
					}
				} else {
					sb.append(vv);
				}
			}
		}
		return sb.toString();
	}

	/**
	 * 创建URI模板格式化处理器
	 * 
	 * @param pattern 模板内容，非空值。
	 * @param quiet   是否安静模式，安静模式不抛出异常。
	 * @return 格式化处理器，非空值。
	 * @throws IllegalArgumentException 模板内容解析失败
	 */
	public static UriFormatter of(String pattern, boolean quiet) throws IllegalArgumentException {
		Objects.requireNonNull(pattern, "消息模板不能为空值");
		int start = pattern.indexOf(MessageFormatter.B_CHAR);
		if (start == -1) {
			// 消息模板不存在变量界定符{}
			return new UriFormatter(pattern, null, quiet);
		}
		ArrayList<CompKey> comps = new ArrayList<>();
		int offset = 0;
		while (start != -1) {
			int next = pattern.indexOf(MessageFormatter.E_CHAR, start);
			if (next == -1) {
				break;
			}
			if (start != offset) {
				comps.add(new CompKey(pattern.substring(offset, start), null));
			}
			String kk = pattern.substring(start + 1, next).trim();
			comps.add(new CompKey("", kk));
			offset = next + 1;
			start = pattern.indexOf(MessageFormatter.B_CHAR, offset);
		}
		if (comps.size() == 0) {
			// 消息模板不存在变量界定符{}
			return new UriFormatter(pattern, null, quiet);
		}
		if (offset != pattern.length()) {
			comps.add(new CompKey(pattern.substring(offset), null));
		}
		return new UriFormatter(pattern, comps.toArray(new CompKey[comps.size()]), quiet);
	}

	/**
	 * 格式化URI模板内容
	 * 
	 * @param pattern 模板内容
	 * @param args    变量哈希表
	 * @return URI模板变量替换后内容
	 */
	public static String format(String pattern, Map<String, ?> args) {
		if (pattern == null || pattern.length() == 0) {
			return pattern;
		}
		return of(pattern, true).build(args);
	}
}
